import "reflect-metadata";

export const createParamDecorator = (keyOrFactory: String | Function) => {
  // target控制器原型 propertyKey 方法名 parameterIndex 1 => 0
  return (data?: any, ...pipes: any[]) =>
    (target: any, propertyKey: any, parameterIndex: number) => {
      const existingParameters =
        Reflect.getMetadata(`params`, target, propertyKey) || [];
       const metatype = Reflect.getMetadata("design:paramtypes", target, propertyKey)[parameterIndex];
      if (keyOrFactory instanceof Function) {
        existingParameters[parameterIndex] = {
          parameterIndex,
          key: "DecoratorFactory",
          factory: keyOrFactory,
          data,
          metatype,
        };
      } else {
        existingParameters[parameterIndex] = {
          parameterIndex,
          key: keyOrFactory,
          data,
          pipes,
          metatype,
        };
      }

      Reflect.defineMetadata(`params`, existingParameters, target, propertyKey);
    };
};

export const Request = createParamDecorator("Request");
export const Req = createParamDecorator("req");
export const Query = createParamDecorator("Query");
export const Headers = createParamDecorator("Headers");
export const Session = createParamDecorator("Session");
export const Ip = createParamDecorator("Ip");
export const Param = createParamDecorator("Param");
export const Body = createParamDecorator("Body");
export const Response = createParamDecorator("Response");
export const Res = createParamDecorator("res");
export const Next = createParamDecorator("Next");
